#include "umString.h"
#include "umapi_libc.h"
#include "umlog.h"

#define TARGET "UMSTRING"

typedef struct
{
	UM_String s;
	UM_CHAR *buff;
	UM_S32 index;
	UM_S32 size;
}UMStringContext;

static UM_VOID checksize(UM_VOID *p, UM_S32 nl)
{
	UMStringContext *str = (UMStringContext *)p;
	if(str->index + nl > str->size)
	{
		UM_S32 newlen = str->size + ((nl % 1024 == 0) 
			? ((nl / 1024 + 1) * 1024) 
			: ((nl / 1024 + 2) * 1024));
//		LOGI("need new size :%d, old size;%d len:%d",
//			newlen, str->size, nl);
		UM_U8 *tmp = umapi_malloc(newlen);
		umapi_memcpy(tmp, str->buff , str->index);
		umapi_free(str->buff);
		str->buff = tmp;
		str->size = newlen;
	}
}
static UM_CHAR *dataPtr(UM_VOID *p)
{
	UMStringContext *str = (UMStringContext *)p;
	return str->buff;
}
static UM_VOID eraseStr(UM_VOID *p, UM_S32 s, UM_S32 l)
{
	UMStringContext *str = (UMStringContext *)p;
	UM_U8 *tmp = umapi_malloc(str->size);
	umapi_memcpy(tmp, str->buff + s , str->index - s - l);
	umapi_free(str->buff);
	str->buff = tmp;
	str->index -= (s + l);
	return ;
}
static UM_VOID appendStr(UM_VOID *p, UM_CHAR* s, UM_S32 len)
{
	UMStringContext *str = (UMStringContext *)p;
	checksize(str, len);
	umapi_memcpy(str->buff + str->index, s, len);
	str->index += len;
}
static UM_VOID appendStr1(UM_VOID *p, UM_CHAR* s, UM_S32 pos, UM_S32 len)
{
	appendStr(p, &s[pos], len);
}
static UM_VOID addStr(UM_VOID *p, UM_CHAR c)
{
	checksize(p, 1);
	UMStringContext *str = (UMStringContext *)p;
	str->buff[str->index++] = c;
}
static UM_CHAR * getAddrByIndex(UM_VOID *p, UM_S32 index)
{
	UMStringContext *str = (UMStringContext *)p;
	if(index>=str->index)
		return UM_NULL;
	return str->buff+index;
}
static UM_S32 sizeStr(UM_VOID *p)
{
	UMStringContext *str = (UMStringContext *)p;
	return str->size;
}
static UM_S32 lengthStr(UM_VOID *p)
{
	UMStringContext *str = (UMStringContext *)p;
	return str->index;
}
static UM_VOID freeStr(UM_VOID *p)
{
	UMStringContext *str = (UMStringContext *)p;
	if(str->buff)
		umapi_free(str->buff);
	umapi_free(str);
	return ;
}

UM_String *createUmString(UM_S32 len)
{
	UMStringContext * ret = (UMStringContext*)umapi_malloc(sizeof(UMStringContext));
	ret->size = len == 0 ? 1024 : len;
	ret->buff = umapi_malloc(ret->size);
	ret->index = 0;
	ret->s.add = addStr;
	ret->s.data = dataPtr;
	ret->s.erase = eraseStr;
	ret->s.append = appendStr;
	ret->s.appendByPos = appendStr1;
	ret->s.getAddr = getAddrByIndex;
	ret->s.size = sizeStr;
	ret->s.getLength = lengthStr;
	ret->s.free = freeStr;
	return (UM_String*)ret;
}

